/*
 * BSM6.0
 *
 * Copyright 2012-2013 (C) SINODATA CO., LTD. All Rights Reserved.
 */
package com.sinodata.bsm.cicp;

import org.apache.log4j.Logger;

import com.sinodata.bsm.cicp.cache.CacheFactory;
import com.sinodata.bsm.cicp.message.AsynMessageListener;
import com.sinodata.bsm.cicp.message.Messenger;
import com.sinodata.bsm.cicp.message.SyncMessageListener;
import com.sinodata.bsm.cicp.service.DeamonService;
import com.sinodata.bsm.cicp.service.ServiceFactory;
import com.sinodata.bsm.cicp.task.TaskManager;
import com.sinodata.bsm.common.constants.SystemStatus;
import com.sinodata.bsm.common.message.ServiceMessage;

/**
 * <p>
 * Description: 
 * </p>
 * 
 * @author tangli
 * @version 1.0
        
 * <p>
 * History: 
 * 
 * Date                     Author         Version     Description
 * ---------------------------------------------------------------------------------
 * 2012-5-9 上午9:06:29          tangli         1.0         To create
 * </p>
 * 
 * @since 
 * @see 
 */
public final class Startup {
    private static final Logger logger = Logger.getLogger(Startup.class);

    private static int status = SystemStatus.STATUS_SETENV;

    public Startup() {

    }

    public void run() {
        while (true) {
            try {
                logger.info("probe status:" + getStatus());
                switch (getStatus()) {
                    case SystemStatus.STATUS_SETENV:
                        setEnv();
                        break;
                    case SystemStatus.STATUS_CONNECT:
                        connect();
                        break;
                    case SystemStatus.STATUS_INIT:
                        init();
                        break;
                    case SystemStatus.STATUS_RUN:
                        work();
                        break;
                    case SystemStatus.STATUS_RESTART:
                        restart();
                        break;
                    case SystemStatus.STATUS_DOWN:
                        exit();
                        break;
                    default:
                        exit();
                        break;
                }
            } catch (Exception e) {
                logger.error("failed to startup statusManager", e);
            }
        }
    }

    private int getStatus() {
        return status;
    }

    /**
     * 设置probe状态
     *
     * @param status
     */
    public static void next(int s) {
        status = s;
    }

    /**
     * 1.初始化配置文件 2.初始化JMS队列 3.初始化与center通信配置 4.初始化service 5.启动Listener
     *
     * @return
     */
    private void setEnv() {
        try {
            ProbeEnv.initEnv();
        } catch (Throwable t) {
            logger.fatal("failed to init probe", t);
        }
        next(SystemStatus.STATUS_CONNECT);
    }

    /**
     * 1.初始化缓存 2.初始化任务 3.通知中心启动成功 4.启动通知队列的监听
     *
     * @return
     */
    private void init() {
        try {
            CacheFactory.getInstance().initCache();
            ServiceFactory.init();
            DeamonService.getInstance().init();
            //TaskControlService.getInstance().start();
            TaskManager.getInstance().initAllTasks();
            SyncMessageListener.getInstance().start();
            AsynMessageListener.getInstance().start();
        } catch (Exception e) {
            logger.fatal("failed to init cache", e);
            next(SystemStatus.STATUS_RESTART);
        }
        next(SystemStatus.STATUS_RUN);
    }

    /**
     * 1.登录中心
     *
     * @return
     */
    private void connect() {
        ServiceMessage message = new ServiceMessage();
        message.setSrvId("probeStatusService");
        message.setMethod("registry");
        message.setParams(new Object[] { ProbeEnv.probeId, ProbeEnv.probeName, ProbeEnv.probeType, ProbeEnv.probeIp });
        message.setNeedReply(true);
        Object response = null;
        try {
            response = Messenger.getInstance().sendServiceMessage(message);
        } catch (Exception e) {
            logger.fatal("连接失败，进行重连");
            try {
                Thread.sleep(60 * 1000L);
            } catch (InterruptedException e1) {
            }
            return;
        }
        if (response != null && response.equals("")) {
            next(SystemStatus.STATUS_INIT);
        } else {
            logger.info("Probe注册失败:" + response);
        }
    }

    /**
     * 1.poll中心，失败则restart
     *
     * @return
     * @throws Exception:如果poll到center中该agent的session与本地的session不一直则抛出异常
     */
    private void work() throws Exception {
        ServiceMessage message = new ServiceMessage();
        message.setSrvId("probeStatusService");
        message.setMethod("finishStartup");
        message.setParams(new Object[] { ProbeEnv.probeId });
        message.setNeedReply(true);
        Object response = null;
        try {
            response = Messenger.getInstance().sendServiceMessage(message);
        } catch (Exception e) {
            logger.fatal("启动失败，开始重启");
            next(SystemStatus.STATUS_RESTART);
            return;
        }
        if (!response.equals("")) {
            logger.fatal("通知中心启动失败，开始重启");
            next(SystemStatus.STATUS_RESTART);
            return;
        }
        while (this.getStatus() == SystemStatus.STATUS_RUN) {
            logger.info("run...");
            Thread.sleep(60 * 1000L);
            //            message = new ServiceMessage();
            //            message.setSrvId("probeStatusService");
            //            message.setMethod("heartbeat");
            //            message.setParams(new Object[] { ProbeEnv.probeId });
            //            message.setNeedReply(true);
            //            try {
            //                response = Messenger.getInstance().sendServiceMessage(message);
            //            } catch (Exception e) {
            //                logger.fatal("连接中心失败，开始重启");
            //                next(SystemStatus.STATUS_RESTART);
            //                return;
            //            }
            //            if (response == null || !response.equals("")) {
            //                logger.fatal("与中心的心跳异常，开始重启");
            //                next(SystemStatus.STATUS_RESTART);
            //                return;
            //            }
        }
    }

    /**
     * 停止probe 1.清空缓存 2.取消采集任务 3.停止通知队列的监听
     *
     * @return
     */
    private void restart() {
        CacheFactory.getInstance().clearCache();
        SyncMessageListener.getInstance().stop();
        AsynMessageListener.getInstance().stop();
        TaskManager.getInstance().stopAllTasks();
        next(SystemStatus.STATUS_CONNECT);
    }

    /**
     * 系统退出
     */
    private void exit() {
        logger.info("probe exit.");
        System.exit(0);
    }

    /**
     * @param args
     * @throws Exception 
     */
    public static void main(String[] args) throws Exception {
        /* IBM JDK读取中文字节流 */
        if (System.getProperty("ibm.stream.nio") == null) {
            System.setProperty("ibm.stream.nio", "true");
        }

        /* 指定jDom解析器 */
        if (System.getProperty("javax.xml.parsers.SAXParserFactory") == null) {
            System.setProperty("javax.xml.parsers.SAXParserFactory", "com.sun.org.apache.xerces.internal.jaxp.SAXParserFactoryImpl");
        }
        ProbeEnv.initConfig();
        new Startup().run();

        "".equals("");
    }

}